package top.goldenyear.porpoise.system.auth.service;

import cn.dev33.satoken.stp.StpUtil;
import com.jfinal.kit.HashKit;
import com.jfinal.kit.Kv;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import cn.hutool.v7.core.data.id.IdUtil;
import cn.hutool.v7.core.date.TimeUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import top.goldenyear.porpoise.common.core.model.Ret;
import top.goldenyear.porpoise.system.account.model.Account;
import top.goldenyear.porpoise.system.account.service.AccountService;
import top.goldenyear.porpoise.system.auth.dto.LoginReq;
import top.goldenyear.porpoise.system.auth.dto.RefreshTokenReq;
import top.goldenyear.porpoise.system.auth.model.Session;

/**
 * @author airhead
 */
@Component
public class LoginService {
  @Inject private SessionService sessionService;
  @Inject private AccountService accountService;

  public Ret login(LoginReq req) {
    String userName = req.getUserName().toLowerCase().trim();
    String password = req.getPassword().trim();
    Account account = accountService.getByAttr("userName", userName);
    if (account == null) {
      return Ret.fail("用户名或密码不正确");
    }

    if (account.isStateLock()) {
      return Ret.fail("账号已被锁定");
    }
    if (account.isStateReg()) {
      return Ret.fail("账号未激活，请先激活账号");
    }

    String salt = account.getSalt();
    String hashedPass = HashKit.sha256(salt + password);

    // 未通过密码验证
    if (!account.getPassword().equals(hashedPass)) {
      return Ret.fail("用户名或密码不正确");
    }

    // 移除敏感信息 password、salt
    account.removeSensitiveInfo();

    Ret token = createToken(account.getId());
    return token;
  }

  public Ret getUserInfo() {
    Integer accountId = StpUtil.getLoginIdAsInt();
    Account account = accountService.getById(accountId);
    List<String> roles = Collections.singletonList("R_SUPER");
    List<String> buttons = new ArrayList<>();

    Kv data =
        Kv.create()
            .set("userId", account.getId())
            .set("userName", account.getNickName())
            .set("roles", roles)
            .set("buttons", buttons);
    return Ret.okWithData(data);
  }

  public Session getSessionById(String sessionId) {
    Session session = sessionService.getById(sessionId);
    if (session == null) {
      return null;
    }

    // 被动式删除 session
    if (session.getExpires().isBefore(TimeUtil.now())) {
      sessionService.deleteById(sessionId);
    }

    return session;
  }

  /** 通过 sessionId 获取 account */
  public Account getAccountById(Integer accountId) {
    Account loginAccount = accountService.getById(accountId);
    if (loginAccount != null) {
      // 移除敏感信息 password、salt
      loginAccount.removeSensitiveInfo();
      // 账户状态 ok
      if (loginAccount.isStateOk()) {
        return loginAccount;
      }
    }

    return null;
  }

  public Ret refreshToken(RefreshTokenReq refreshTokenReq) {
    Session session = sessionService.getById(refreshTokenReq.getRefreshToken());
    if (session == null) {
      return Ret.fail("无效的refresh token");
    }

    if (session.getExpires().isBefore(TimeUtil.now())) {
      return Ret.fail("refresh token已过期");
    }

    return createToken(session.getAccountId());
  }

  private Ret createToken(Integer accountId) {
    StpUtil.login(accountId);
    String token = StpUtil.getTokenValue();
    // session 存活时间设置为 3 天
    long timeToLiveSeconds = 3 * 24 * 60 * 60;
    sessionService.storeToken(accountId, "token", timeToLiveSeconds, token);
    String refreshToken = IdUtil.fastSimpleUUID();
    sessionService.storeToken(accountId, "refresh_token", timeToLiveSeconds * 2, refreshToken);


    StpUtil.setTokenValue(token);
    // 用于设置 cookie 的存活时间
    return Ret.okWithData(
        Kv.create()
            .set("token", token)
            .set("refreshToken", refreshToken)
            .set("timeToLiveSeconds", timeToLiveSeconds));
  }
}
